package com.moshang.blog.controller.base;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.moshang.blog.core.annotation.SystemLog;
import com.moshang.blog.core.constant.BussinessCode;
import com.moshang.blog.core.constant.Constants;
import com.moshang.blog.core.constant.MySysUser;
import com.moshang.blog.core.utils.*;
import com.moshang.blog.entity.*;
import com.moshang.blog.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.*;

/**
 * @program: blog
 * @description: ${description}
 * @author: xieweiwei
 * @create: 2018-09-26 10:50
 **/
@Controller
@Transactional(rollbackFor = MyException.class)
public class LoginController extends BaseController {
    private final Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private SysUsersService sysUsersService;
    @Autowired
    private SiteService siteService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @RequestMapping("toLogin")
    public String toLogin() {
        Subject sub = SecurityUtils.getSubject();
        if (sub.isAuthenticated()) {
            return "/back/index";
        } else {
            RestResponse.failure("请重新登录");
            return "back/login/login";
        }

    }
    @RequestMapping("toRegister")
    public String toRegister() {
            return "back/login/register";
        }
    /**
     * 生成验证码
     */
    @RequestMapping("/captcha")
    public void Captcha(HttpServletResponse response, HttpSession session) throws IOException {
        CreateImageCode vCode = new CreateImageCode(116, 36, 5, 10);
        session.setAttribute("code", vCode.getCode());
        vCode.write(response.getOutputStream());
    }
    /**
     * 发送短信验证码
     */
    @RequestMapping("/sendSms")
    @ResponseBody
    public RestResponse sendSms(@RequestParam("phone") String phone, HttpSession session) throws IOException {
        String phoneCode=SendSMSUtils.sendMesModel(phone);
        if (StringUtils.isNotBlank(phoneCode)){
            if (StringUtils.isNotBlank((String)session.getAttribute("phoneCode"))){
                session.removeAttribute("phoneCode");
            }
            session.setAttribute("phoneCode", phoneCode);
            return  RestResponse.success("发送成功");
        }else {
            return RestResponse.failure("发送失败");
        }

    }
    @PostMapping("register")
    @ResponseBody
    @SystemLog("注册用户")
    public RestResponse register(SysUser sysUser, HttpServletRequest request) {
        if (StringUtils.isBlank(sysUser.getUserName()) || StringUtils.isBlank(sysUser.getRealName())) {
            return RestResponse.failure("用户名或者密码不能为空");
        }
        String code = request.getParameter("code");
        if (StringUtils.isBlank(code)) {
            return RestResponse.failure("验证码不能为空");
        }
        Map<String, Object> map = Maps.newHashMap();
        String error = null;
        HttpSession session = request.getSession();
        if (session == null) {
            return RestResponse.failure("session超时");
        }
        String trueCode = (String) session.getAttribute(BussinessCode.PHONE_VALIDATE_CODE);
        if (StringUtils.isBlank(trueCode)) {
            return RestResponse.failure("验证码超时");
        }
        //检查时候存在该登陆用户信息
        SysUser sysUser1=sysUsersService.findByUserName(sysUser.getUserName());
        if (sysUser1!=null){
            error="该登录名已存在";
        }
        if (StringUtils.isBlank(code) || !trueCode.toLowerCase().equals(code.toLowerCase())) {
            error = "验证码错误";
        }
        if (StringUtils.isBlank(error)) {
            ToolUtil.entryptPassword(sysUser);
            sysUser.setCreateTime(new Date());
            sysUser.setUpdateTime(new Date());
            sysUser.setIsActivited(0);
            sysUsersService.save(sysUser);
            //设置角色为普通用户
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setRoleId(3);
            sysUserRole.setUserId(sysUser.getId());

            sysUserRoleService.save(sysUserRole);
            map.put("url", "login");
            return RestResponse.success("注册成功").setData(map);
        } else {
            return RestResponse.failure(error);
        }
    }
    @GetMapping("login")
    public String login(HttpServletRequest request) {
        logger.info("跳到这边的路径为:" + request.getRequestURI());
        Subject s = SecurityUtils.getSubject();
        logger.info("是否记住登录--->" + s.isRemembered() + "<-----是否有权限登录----->" + s.isAuthenticated() + "<----");
        if (s.isAuthenticated()) {
            return "redirect:back/index";
        } else {
            return "back/login/login";
        }
    }

    @PostMapping("loginCheck")
    @ResponseBody
    @SystemLog("用户登录")
    public RestResponse loginMain(HttpServletRequest request) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String rememberMe = request.getParameter("rememberMe");
        String code = request.getParameter("code");
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            return RestResponse.failure("用户名或者密码不能为空");
        }
        if (StringUtils.isBlank(rememberMe)) {
            return RestResponse.failure("记住我不能为空");
        }
        if (StringUtils.isBlank(code)) {
            return RestResponse.failure("验证码不能为空");
        }
        Map<String, Object> map = Maps.newHashMap();
        String error = null;
        HttpSession session = request.getSession();
        if (session == null) {
            return RestResponse.failure("session超时");
        }
        String trueCode = (String) session.getAttribute(BussinessCode.VALIDATE_CODE);
        if (StringUtils.isBlank(trueCode)) {
            return RestResponse.failure("验证码超时");
        }
        if (StringUtils.isBlank(code) || !trueCode.toLowerCase().equals(code.toLowerCase())) {
            error = "验证码错误";
        } else {
            /*就是代表当前的用户。*/
            Subject user = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(username, password, Boolean.valueOf(rememberMe));
            try {
                user.login(token);
                if (user.isAuthenticated()) {
//                    Session onlinesession = onlineSessionDAO.readSession(user.getSession().getId());
//                    OnlineSession onlineSession = (OnlineSession) session;
//                    AsyncFactory.syncSessionToDb(onlineSession);
                    map.put("url", "index");
                }
            } catch (IncorrectCredentialsException e) {
                error = "登录密码错误.";
            } catch (ExcessiveAttemptsException e) {
                error = "登录失败次数过多";
            } catch (LockedAccountException e) {
                error = "帐号已被锁定.请联系管理员！";
            } catch (DisabledAccountException e) {
                error = "帐号已被禁用.";
            } catch (ExpiredCredentialsException e) {
                error = "帐号已过期.";
            } catch (UnknownAccountException e) {
                error = "帐号不存在";
            } catch (UnauthorizedException e) {
                error = "您没有得到相应的授权！";
            }
        }
        if (StringUtils.isBlank(error)) {
            return RestResponse.success("登录成功").setData(map);
        } else {
            return RestResponse.failure(error);
        }
    }

    @GetMapping("/index")
    public String showView(Model model) {
        Subject sub = SecurityUtils.getSubject();
        if (!sub.isAuthenticated()) {
            ThreadContext.remove(ThreadContext.SUBJECT_KEY);
            return toLogin();
        }
        SysUser user = sysUsersService.findUserById(MySysUser.id());
        if (StringUtils.isBlank(user.getImage())){
            user.setImage(Constants.DEFAULT_IMAGE);
        }
        model.addAttribute("user", user);
        Site site = siteService.getCurrentSite();
        model.addAttribute("site", site);
        return "back/index";
    }

    @GetMapping("main")
    public String main(Model model) {
        Map map = sysUsersService.selectUserMenuCount();
        SysUser user = sysUsersService.findUserById(MySysUser.id());
        Set<SysMenu> menus = user.getMenus();
        java.util.List<SysMenu> showMenus = Lists.newArrayList();
        if (menus != null && menus.size() > 0) {
            for (SysMenu menu : menus) {
                if (StringUtils.isNotBlank(menu.getHref())) {
                    Long result = (Long) map.get(menu.getPermission());
                    if (result != null) {
                        menu.setDataCount(result.intValue());
                        showMenus.add(menu);
                    }
                }
            }
        }
        List<String> roleNameList = new ArrayList<>();

        Set<SysRole> roles = user.getRoleLists();
        if (roles != null && roles.size() > 0) {
            for (SysRole role : roles) {
                roleNameList.add(role.getRoleName());
            }
        }
        if (StringUtils.isBlank(user.getImage())){
            user.setImage(Constants.DEFAULT_IMAGE);
        }
        showMenus.sort(new MenuComparator());
        Site site = siteService.getCurrentSite();
        model.addAttribute("roleNames", roleNameList.toString());
        model.addAttribute("userMenu", showMenus);
        model.addAttribute("site", site);
        model.addAttribute("user", user);
        return "back/main";
    }

    class MenuComparator implements Comparator<SysMenu> {

        @Override
        public int compare(SysMenu o1, SysMenu o2) {
            if (o1.getSort() > o2.getSort()) {
                return -1;
            } else {
                return 0;
            }
        }
    }





}
